/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.gameloft.glf;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.view.WindowManager;
import android.view.Surface;
import android.view.OrientationEventListener;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;

import android.os.Bundle;
//import android.util.Log;

public class GL2JNIActivity extends Activity {

	static GL2JNIActivity s_activity = null;
    GL2JNIView m_view;
    private OrientationEventListener m_orientationListener;
    private SensorEventListener m_sensorEventListener;
    private SensorManager m_sensorManager;
    private Sensor m_accelerometer;
    private boolean m_accelerometerEnabled;
    boolean m_isInitialized = false;
	String m_libName = "gl2jni";
    
    public void setResourcePath(String path) {
    	GL2JNILib.setResourcePath(path);
    }
    
    public void setLibName(String name) {
    	m_libName = name;
    }
    
    public void enableAccelerometer(boolean enabled, float frequency) {
    	System.out.print("enableAccelerometer " + enabled + ": " + frequency + " Hz");
    	
    	updateAccelerometer(enabled);
    	m_accelerometerEnabled = enabled;
    }
    
    protected void updateAccelerometer(boolean enabled) {
    	m_sensorManager.unregisterListener(m_sensorEventListener);
    	if(enabled) {
    		m_sensorManager.registerListener(m_sensorEventListener, m_accelerometer, SensorManager.SENSOR_DELAY_GAME);
    	}
    }
    
    protected void suspendResumeSensors(boolean resume) {
    	if(resume) {
    		updateAccelerometer(m_accelerometerEnabled);
    	} else {
    		updateAccelerometer(false);
    	}
    }

    @Override protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        
        if(startInstallerIfPresent()) {
        	return;
        }
        
        startGame();
    }
    
    boolean startInstallerIfPresent() {
    	try {
    		String installerClassName = this.getPackageName() + ".installer.GameInstaller";
    		Class cls = Class.forName(installerClassName);
    		
    		// check if already started
    		boolean sbStarted = false;
    		try {
    			java.lang.reflect.Field field = cls.getField("sbStarted");
    			sbStarted = field.getBoolean(null); // GameInstaller.sbStarted static field
    		} catch(Exception e) {}
    		
			if(!sbStarted) {
				// System.out.println("Game", "------- Game::onCreate(), start installer ------");
				Intent i = new Intent();
				i.setClassName(this.getPackageName(), installerClassName);
				
				Log.d("GL2JNIActivity", "startActivity: " + installerClassName);
				startActivityForResult(i, 0);
				return true;
			}
		} catch(ClassNotFoundException e) {
			
		} catch(Throwable t) {
			t.printStackTrace();
		}
		return false;
    }
    
    protected void startGame() {
    	Log.d("GL2JNIActivity", "startGame");
    	
    	s_activity = this;
        System.loadLibrary(m_libName);
        int rotation = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay().getRotation();
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        
        m_sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        m_accelerometer = m_sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        m_orientationListener = new MyOrientationEventListener(this);
        m_sensorEventListener = new MySensorEventListener();

        if(!m_isInitialized && rotation == Surface.ROTATION_0) {
            GL2JNILib.init();
            m_isInitialized = true;
        }
    }
    
    @Override public void onConfigurationChanged(android.content.res.Configuration newConfig) {
    	super.onConfigurationChanged(newConfig);
    	
    	if(!m_isInitialized) {
    		GL2JNILib.init();
    		m_isInitialized = true;
    	}
    }

    @Override protected void onPause() {
        super.onPause();
        if(m_view != null) {
        	m_view.onPause();
        	suspendResumeSensors(false);
        	// GL2JNILib.stateChanged(false); will be called from ContextFactory.destroyContext (opengl thread)
        }
    }

    @Override protected void onResume() {
        super.onResume();
        if(m_view != null) {
        	suspendResumeSensors(true);
        	m_view.onResume();
        	// GL2JNILib.stateChanged(true) will be called from Renderer.onSurfaceCreated;  (opengl thread)
        }
    }
    
    @Override protected void onDestroy() {
    	super.onDestroy();
    	
    	int pid = android.os.Process.myPid();
    	android.os.Process.killProcess(pid); 
    }
    
    class MyOrientationEventListener extends OrientationEventListener {
    	   	
    	MyOrientationEventListener(Context context) {
    		super(context);
    		enable();
    	}
    	
    	public void onOrientationChanged(int orientation) {
    		if(m_view != null) {
    			if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
    				orientation = (orientation + 90) % 360;
    			GL2JNILib.orientationChanged(orientation);
    		}
    	}
    }
    
    class MySensorEventListener implements SensorEventListener {
    	
    	public void onAccuracyChanged(Sensor sensor, int accuracy) {
    	}
    	
    	public void onSensorChanged(SensorEvent event) {
            // We send acceleration data in the same format as on iPhone/iPad/iPod,
    		// that is : not filtered, and with units expressed in G along the X, Y and Z 
    		// axes. Recall that on Android, raw acceleration data have units expressed 
    		// in m/s**2 (N.B. 1G is approximately equal to 9.81 m/s**2).
    		// 
    		// Also note that on Android the acceleration vector is given in the 
    		// opposite direction than the one on iPhone/iPad/iPod (on iPhone/iPad/iPod,
    		// a device lying flat on a table will return a (0, 0, -1) acceleration 
    		// vector, whereas on Android, it will return (0, 0, 9.81)).
    		//
    		// On the other side, on both iPhone/iPad/iPod and Android, the raw data 
    		// is not filtered (noisy), and the reference coordinate frame is the same
    		// (the origin is at the center of the screen, the Y axis goes along the 
    		// longest side of the device, the X axis goes along its shortest side, 
    		// the Z axis is perpendicular to the screen, and the coordinate system
    		// is right-handed).
            final float convertFromAndroidToIPhone = -(1.0f / 9.81f);
    		GL2JNILib.accelerometerEvent(event.values[0] * convertFromAndroidToIPhone, 
    									 event.values[1] * convertFromAndroidToIPhone, 
    									 event.values[2] * convertFromAndroidToIPhone);
    	}
    }
}
